package com.vividsolutions.jts.addons;

import java.util.List;

import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.GeometryCollection;
import com.vividsolutions.jts.geom.GeometryFactory;
import com.vividsolutions.jts.geom.LineString;
import com.vividsolutions.jts.geom.Point;
import com.vividsolutions.jts.geom.Polygon;
import com.vividsolutions.jts.io.WKTReader;

/**
 * draw geom using a Bursh
 * @author Shen
 *
 */
public class GeomPainter {
	Brush brush;
	private double radius = 5;

	public GeomPainter(Brush painter) {
		setBrush(painter);
	}

	public void setBrush(Brush painter) {
		this.brush = painter;
	}

	public Brush getBrush() {
		return this.brush;
	}

	public void draw(Geometry geom) {
		if (geom == null) {
			return;
		}
		if (geom instanceof GeometryCollection) {
			GeometryCollection geoms = (GeometryCollection) geom;
			for (int i = 0; i < geoms.getNumGeometries(); i++) {
				Geometry theGeom = geoms.getGeometryN(i);
				draw(theGeom);
			}
			return;
		}
		brush.startPath();
		if (geom instanceof Point) {
			Point point = (Point) geom;
			brush.drawCircle(point.getX(), point.getY(), radius);
		} else if (geom instanceof LineString) {
			LineString line = (LineString) geom;
			for (Coordinate coord : line.getCoordinates()) {
				brush.lineTo(coord.x, coord.y);
			}
			brush.stroke();
		} else if (geom instanceof Polygon) {
			Polygon polygon = (Polygon) geom;
			LineString ring = polygon.getExteriorRing();
			for (Coordinate coord : ring.getCoordinates()) {
				brush.lineTo(coord.x, coord.y);
			}

			brush.fill();
			brush.stroke();

			int n = polygon.getNumInteriorRing();
			for (int i = 0; i < n; i++) {
				LineString interiorRing = polygon.getInteriorRingN(i);
				brush.startPath();
				for (Coordinate coord : interiorRing.getCoordinates()) {
					brush.lineTo(coord.x, coord.y);
				}
				brush.setColor(null, "FFFFFF");
				brush.fill();
				brush.stroke();
			}

		} else {
			System.out.println(geom.getClass().getName() + " is not supported");
		}

	}

	public GeomPainter ctx(Object ctx) {
		this.brush.setCtx(ctx);
		return this;
	}

	public void drawSample() {
		brush.setColor("0000FF", "00FF00");
		WKTReader reader = new WKTReader();
		try {
			Geometry g1 = reader.read("POINT(100 30)");
			this.set("0000FF", "00FF00", 1).draw(g1);

			Geometry g2 = reader.read("LINESTRING (150 25, 50 70, 150 60)");
			this.set("0000FF", "00FF00", 1).draw(g2);

			Geometry g3 = reader.read("LINESTRING (150 35, 0 0, 150 100)");
			this.set("0000FF", "00FF00", 1).draw(g3);

			this.set("FF00FF", null, 1).draw(g2.intersection(g3));

			Geometry g4 = reader
					.read("POLYGON ((130 110, 110 120, 120 140, 140 140, 130 110))");
			this.set("0000FF", "00FF00", 1).draw(g4);

			Geometry g4_buffer = g4.buffer(10);
			this.set("0000FF", null, 0.8).draw(g4_buffer);

			Geometry g5 = g4_buffer.getEnvelope();

			this.set("FF0000", null, 1).draw(g5);

			Geometry g6 = reader
					.read("POLYGON ((35 10, 10 20, 15 40, 45 45, 35 10),"
							+ "(20 30, 35 35, 30 20, 20 30))");
			this.set("0000FF", "00FF00", 1).draw(g6);

		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public GeomPainter reset() {
		this.set("FFFF00", "00FF00", 0.8);
		return this;
	}

	public GeomPainter set(String color) {
		return set(color, color, 0.8);
	}

	public GeomPainter set(String stroke, String fill, double opacity) {
		this.brush.setColor(stroke, fill);
		this.brush.setOpacity(opacity);
		return this;
	}

	public void draw(List<Geometry> helper) {
		for (Geometry geometry : helper) {
			draw(geometry);
		}
	}
}
